/**
 * @brief 设备媒体基类
 * date:2023/12/18 
 * author:Coolio
 */
#ifndef ZMEDIASERVER_SRC_CACHE_DEVICEMEDIABASE_H
#define ZMEDIASERVER_SRC_CACHE_DEVICEMEDIABASE_H
#include <string>
#include <stdint.h>
#include <memory>
#include <future>
#include <utility>
#include "Poller/Timer.h"
#include "Util/logger.h"
#include "SerializeObject.h"
#include "CacheThreadPool.h"
using namespace std;
using namespace toolkit;

struct TimeRange {
	time_t startTime;
	time_t endTime;
    TimeRange(time_t stime,time_t etime) {
        startTime = stime;
        endTime = etime;
    }
    bool IsValid() const {
        return startTime < endTime && (endTime - startTime) > 60;//超过一分钟
    }
};
enum class SubscriberStateType : uint8_t {
    SST_UNKNOWN = 0,//未知初始化状态
    SST_PAUSE ,//暂停推流
    SST_PUSHING ,//正在发送
    SST_CLOSED ,//关闭
};

string getSubscriberStateTypeString(SubscriberStateType type);

typedef struct CacheTierInfo{
    time_t target_start_time; ///目标缓存片段的开始时间
    int  pts_offset; ///将该帧投递到目标缓存片段需要修改的pts差值(考虑到不同的录像请求的起始pts值并不连续,需要减去offset才能让pts在合并缓存后连续)
    CacheTierInfo(time_t _target_start_time,int _pts_offset) {
        target_start_time = _target_start_time;
        pts_offset = _pts_offset;
    }
    CacheTierInfo(){
        target_start_time = 0;
        pts_offset = 0;
    }
} CacheTierInfo;

#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)

#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))

class DeviceMediaBase : public SerializeObject{
    public:
        DeviceMediaBase();
        ~DeviceMediaBase();
        /**
         * 增加缓存的连续性信息
         */
        void UpdateCacheTier(const time_t after_start_time,const time_t before_start_time,const int pts_offset);
        virtual std::string GetDesc() = 0; 
    protected:    
        std::map<time_t,CacheTierInfo> m_cachetier;//key标记的缓存是value标记的缓存的连续,得到帧后需要检查该结构,如果存在映射,则需要投递到映射后的时间标记的缓存片段里去
        //本socket绑定的poller线程，事件触发于此线程
        EventPoller::Ptr m_poller;
};
#endif
